<template>
	<div class="upload-file w100">
		<el-upload
			v-if="!exportShow"
			ref="upload"
			class="avatar-uploader"
			:limit="limit"
			:on-exceed="exceedFn"
			:http-request="uploadFn"
			:show-file-list="false"
			v-bind="$attrs"
		>
			<el-button icon="Upload" plain class="m-r-10">上传文件</el-button>
			<template #tip v-if="showTip">
				<div class="el-upload__tip">
					请上传
					<template v-if="fileSize">
						不超过
						<span>{{ fileSize }}MB</span>
					</template>
					<template v-if="fileType.length">
						格式为
						<b style="color: #f56c6c">{{ fileType.join('/') }}</b>
					</template>
					的文件
				</div>
			</template>
		</el-upload>
		<!-- 上传的文件列表 -->
		<div v-if="fileList.length" class="fileList">
			<TransitionGroup name="fade-transform" appear>
				<div
					class="fileList_item"
					v-for="(file, index) in fileList"
					:key="file.id"
					@click.prevent="previewFn(file, index)"
				>
					<Files style="height: 1em; margin-right: 8px; margin-top: 3px" />
					<el-tooltip :content="`${file.fileName}${file.fileSuffix}`" placement="top" :disabled="isDisabled">
						<span class="name flex" v-if="editIndex === index">
							<el-input
								autofocus
								v-model="file.fileName"
								size="small"
								class="editInput f1 w0"
								@keyup.enter="editFn(file)"
								@blur="editFn(file)"
							/>
							<span class="inline">{{ file.fileSuffix }}</span>
						</span>
						<span class="name" v-else @mouseover="isShowTootip">{{ file.fileName }}{{ file.fileSuffix }}</span>
					</el-tooltip>
					<span class="button">
						<el-tooltip effect="dark" content="保存" placement="top">
							<el-icon class="pointer m-l-5" @click.stop.prevent="editFn(file)" v-show="editIndex === index">
								<circle-check />
							</el-icon>
						</el-tooltip>
						<el-tooltip effect="dark" content="编辑" placement="top">
							<el-icon
								class="pointer m-l-5"
								@click.stop.prevent="editIndex = index"
								v-show="editIndex !== index && !exportShow"
							>
								<edit />
							</el-icon>
						</el-tooltip>
						<el-tooltip effect="dark" content="下载" placement="top">
							<el-icon class="pointer m-l-5" @click.stop.prevent="downloadFn(file)" v-show="editIndex !== index">
								<download />
							</el-icon>
						</el-tooltip>
						<el-tooltip effect="dark" content="删除" placement="top">
							<el-icon
								class="pointer m-l-5"
								@click.stop.prevent="closeFn(index)"
								v-show="editIndex !== index && !exportShow"
							>
								<close />
							</el-icon>
						</el-tooltip>
					</span>
				</div>
			</TransitionGroup>
		</div>
		<!-- 图片预览 -->
		<el-dialog v-model="dialogVisible" title="图片预览">
			<el-image :src="dialogImageUrl" fit="contain" preview-teleported />
		</el-dialog>
		<!-- PDF图片预览 -->
		<el-dialog v-model="dialogVisiblePdf" title="PDF图片预览" fullscreen>
			<iframe :src="dialogImageUrl" width="100%" height="100%" />
		</el-dialog>
	</div>
</template>

<script setup name="MyFileUpload">
import { formContextKey as elFormKey, formItemContextKey as elFormItemKey, genFileId } from 'element-plus';
/**
 * 请求接口
 */
import { downloadGet } from '@u/axios';
import { rdfileRename } from '@a/public';
import { uploadData } from '@a/module';

const emits = defineEmits(['update:modelValue']),
	elForm = inject(elFormKey, {}),
	elFormItem = inject(elFormItemKey, {}),
	/***
	 * props
	 * @property {Array} modelValue v-model绑定的值，
	 * @property {Number} fileSize 上传文件大小的限制（默认为100M）
	 * @property {Array} fileType 可以上传的文件类型，默认为[]（就是不校验文件类型）
	 * @property {Boolean} isShowTip 是否显示上传框的提示（默认为true）
	 * @property {Boolean} download 是否允许下载文件（默认为true）
	 * @property {Boolean} disabled 是否允许操作（上传文件等操作，如果不传默认按照form表单的disabled值）
	 * @property {Number} limit 上传附件数量（默认为1）
	 */
	props = defineProps({
		modelValue: [Array, String, Object],
		fileSize: {
			type: Number,
			default: 100
		},
		fileType: {
			type: Array,
			default: () => []
		},
		isShowTip: {
			type: Boolean,
			default: true
		},
		download: {
			type: Boolean,
			default: true
		},
		disabled: Boolean,
		limit: {
			type: Number,
			default: 1
		}
	});
// 文件上传弹窗数据
let upload = shallowRef(null),
	dialogImageUrl = ref(''),
	dialogVisible = ref(false),
	dialogVisiblePdf = ref(false),
	editIndex = ref(null),
	isDisabled = ref(true);

// 是否显示提示
let showTip = computed(() => props.isShowTip && (props.fileType ?? props.fileSize)),
	// 是否禁用上传功能
	exportShow = computed(() => props.disabled || elForm?.disabled),
	fileList = ref([]);

watch(
	() => props.modelValue,
	(val = []) => {
		if (!isEqual(val, fileList.value)) {
			const valData = isArray(val) ? val : [val];
			fileList.value =
				valData?.map((item) => ({
					id: item.id,
					downloadUrl: item.downloadUrl || item.storageUrl,
					fileName: item.fileName,
					fileSizeFormat: item.fileSizeFormat,
					fileSize: item.fileSize,
					fileSuffix: item.fileSuffix
				})) || [];
		}
	}
);

watch(
	() => fileList,
	(val) => {
		emits('update:modelValue', val);
		elForm.validateField(elFormItem.prop);
	},
	{ deep: true }
);

function exceedFn(files) {
	unref(upload).clearFiles();
	const file = files[0];
	file.uid = genFileId();
	unref(upload).handleStart(file);
	unref(upload).submit();
}
// 文件上传
function uploadFn(data) {
	if (handleBeforeUpload(data.file)) {
		let formdata = new FormData();
		formdata.append('file', data.file);
		uploadData(formdata)
			.then((res) => {
				if (props.limit === 1) fileList.value = [];
				nextTick(() => {
					fileList.value.push({
						id: res.data.id,
						downloadUrl: res.data.downloadUrl,
						fileName: res.data.fileName.split('.')[0],
						fileSizeFormat: res.data.fileSizeFormat,
						fileSize: res.data.fileSize,
						fileSuffix: res.data.fileSuffix
					});
				});
			})
			.catch(() => {
				unref(upload).clearFiles();
			});
	} else {
		if (props.limit === 1) fileList.value = [];
	}
}
// 上传前校检格式和大小
function handleBeforeUpload(file) {
	// 校检文件类型
	if (props.fileType.length) {
		let fileExtension = '';
		if (file.name.lastIndexOf('.') > -1) {
			fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1);
		}
		const isTypeOk = props.fileType.some((type) => {
			if (file.type.indexOf(type) > -1) return true;
			if (fileExtension && fileExtension.indexOf(type) > -1) return true;
			return false;
		});
		if (!isTypeOk) {
			msgError(`文件格式不正确, 请上传${props.fileType.join('/')}格式文件!`);
			return false;
		}
	}
	// 校检文件大小
	if (props.fileSize) {
		const isLt = file.size / 1024 / 1024 < props.fileSize;
		if (!isLt) {
			msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
			return false;
		}
	}
	return true;
}
// 文件名修改
function editFn(file) {
	rdfileRename({ id: file.id, fileName: file.fileName }).then(() => {
		msgSuccess('修改成功！');
		editIndex.value = null;
	});
}
// 文件预览
function previewFn(file, index) {
	if (editIndex.value !== index) {
		if (['.png', '.jpg', '.jpeg'].includes(file.fileSuffix)) {
			dialogImageUrl.value = file.downloadUrl;
			dialogVisible.value = true;
		} else if (['.pdf'].includes(file.fileSuffix)) {
			dialogVisiblePdf.value = true;
			dialogImageUrl.value = file.downloadUrl;
		}
	}
}
// 文件下载
function downloadFn(data) {
	downloadGet({ url: data.downloadUrl, fileName: data.fileName + data.fileSuffix });
}
// 删除文件
function closeFn(file) {
	confirm('此操作将删除该数据, 是否继续?')
		.then(() => {
			unref(upload).clearFiles();
			if (props.limit === 1) {
				fileList.value = [];
			} else {
				const index = fileList.value.findIndex((item) => item.id === file.id);
				fileList.value.splice(index, 1);
			}
			msgSuccess('删除成功');
		})
		.catch(() => {
			msgInfo('已取消删除！');
		});
}
// 文本超出出tip e.target.clientWidth; 文本可视宽度 e.target.scrollWidth; 文本实际宽度
function isShowTootip(e) {
	isDisabled.value = e.target.scrollWidth <= e.target.clientWidth;
}
</script>

<style scoped lang="scss">
:deep() {
	.el-upload__tip {
		color: #858ebd;
		margin-top: 0;
	}
	.el-dialog.is-fullscreen {
		display: flex;
		flex-direction: column;
		.el-dialog__body {
			height: 0;
			flex: 1;
		}
	}
}
.fileList {
	max-height: 92px;
	overflow-y: auto;
	overflow-x: hidden;
	background: rgba(76, 105, 255, 0.05);
	border-radius: 4px;
	padding: 4px;
	box-sizing: border-box;
	transition: all 0.3s;
	&_item {
		display: flex;
		padding: 4px;
		height: 20px;
		line-height: 20px;
		border-radius: 4px;
		cursor: pointer;
		box-sizing: content-box !important;
		.icon-file {
			color: #6d6d6d;
			font-size: 12px;
			margin: 4px 4px 0 0;
		}
		.name {
			flex: 1;
			width: 0;
			text-align: left;
			text-overflow: ellipsis;
			overflow: hidden;
			white-space: nowrap;
			color: rgba(58, 63, 99, 1);
			.editInput {
				height: 20px;
				line-height: 20px;
				:deep(.el-input__inner) {
					height: 19px;
					line-height: 20px;
					padding: 0 5px;
				}
			}
		}
		.button {
			display: none;
		}
		&:hover {
			background: #fff;
			box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
			transition: 0.3s;
			.button {
				font-size: 14px;
				display: inline-block;
				.icon-download {
					color: rgba(68, 88, 254, 1);
				}
				.icon-edit,
				.el-icon-circle-check {
					color: rgba(0, 208, 181, 1);
				}
				.icon-close {
					color: rgba(255, 60, 101, 1);
				}
			}
		}
	}
}
</style>
